libobs_wrapper\display\window_manager/
position_trait.rs1#[cfg(windows)]
2use windows::Win32::{
3 Foundation::HWND,
4 Graphics::Gdi::{RedrawWindow, RDW_ERASE, RDW_INVALIDATE},
5 UI::WindowsAndMessaging::{
6 SetWindowPos, HWND_BOTTOM, SWP_NOACTIVATE, SWP_NOCOPYBITS, SWP_NOSIZE, SWP_NOZORDER,
7 SWP_SHOWWINDOW,
8 },
9};
10
11use crate::display::window_manager::WindowPositionTrait;
12use crate::utils::ObsError;
13use crate::{display::ObsDisplayRef, run_with_obs};
14
15impl WindowPositionTrait for ObsDisplayRef {
16 fn set_render_at_bottom(&self, _render_at_bottom: bool) -> Result<(), ObsError> {
17 log::trace!("Set render bottom");
18 #[cfg(windows)]
19 if let Some(m) = self.child_window_handler.as_ref() {
20 let mut m = m
21 .write()
22 .map_err(|e| ObsError::LockError(format!("{:?}", e)))?;
23
24 m.render_at_bottom = _render_at_bottom;
25 }
26 Ok(())
27 }
28
29 fn get_render_at_bottom(&self) -> Result<bool, ObsError> {
30 #[cfg(windows)]
31 if let Some(m) = self.child_window_handler.as_ref() {
32 let m = m
33 .read()
34 .map_err(|e| ObsError::LockError(format!("{:?}", e)))?;
35 return Ok(m.render_at_bottom);
36 }
37
38 Ok(false)
39 }
40
41 fn set_pos(&self, x: i32, y: i32) -> Result<(), ObsError> {
42 log::trace!("Set pos {x} {y}");
43
44 #[cfg(windows)]
45 if let Some(m) = self.child_window_handler.as_ref() {
46 let mut m = m
47 .write()
48 .map_err(|e| ObsError::LockError(format!("{:?}", e)))?;
49
50 if !m.has_display_handle() {
51 return Err(ObsError::InvalidOperation(
52 "preview child has no OBS display handle".to_string(),
53 ));
54 }
55
56 let insert_after = if m.render_at_bottom {
57 HWND_BOTTOM
58 } else {
59 HWND::default()
60 };
61
62 m.x = x;
63 m.y = y;
64
65 unsafe {
66 let flags = SWP_NOCOPYBITS | SWP_NOSIZE | SWP_NOACTIVATE;
69 SetWindowPos(
71 m.window_handle.get_hwnd(),
72 Some(insert_after),
73 x,
74 y,
75 1_i32,
76 1_i32,
77 flags,
78 )
79 .map_err(|e| ObsError::DisplayCreationError(format!("{:?}", e)))?;
80 }
81
82 drop(m); self.update_color_space()?;
85 return Ok(());
86 }
87
88 *self.render_state.position.write().map_err(|_| {
89 ObsError::LockError("display render position lock poisoned".to_string())
90 })? = (x, y);
91
92 self.update_color_space()?;
93 Ok(())
94 }
95
96 fn set_size(&self, width: u32, height: u32) -> Result<(), ObsError> {
97 log::trace!("Set size {width} {height}");
98
99 #[cfg(windows)]
100 if let Some(m) = self.child_window_handler.as_ref() {
101 let mut m = m
102 .write()
103 .map_err(|e| ObsError::LockError(format!("{:?}", e)))?;
104
105 if !m.has_display_handle() {
106 return Err(ObsError::InvalidOperation(
107 "preview child has no OBS display handle".to_string(),
108 ));
109 }
110
111 m.width = width;
112 m.height = height;
113
114 unsafe {
115 SetWindowPos(
118 m.window_handle.get_hwnd(),
119 None,
120 m.x,
121 m.y,
122 width as i32,
123 height as i32,
124 SWP_NOCOPYBITS | SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW,
125 )
126 .map_err(|e| ObsError::DisplayCreationError(format!("{:?}", e)))?;
127
128 let _ = RedrawWindow(
129 Some(m.window_handle.get_hwnd()),
130 None,
131 None,
132 RDW_ERASE | RDW_INVALIDATE,
133 );
134 }
135 }
136
137 let pointer = self.as_ptr();
138 run_with_obs!(self.runtime, (pointer), move || {
139 unsafe {
140 libobs::obs_display_resize(pointer.get_ptr(), width, height);
143 libobs::obs_display_update_color_space(pointer.get_ptr());
145 }
146 })?;
147 Ok(())
148 }
149
150 fn get_pos(&self) -> Result<(i32, i32), ObsError> {
151 #[cfg(windows)]
152 if let Some(m) = self.child_window_handler.as_ref() {
153 let m = m
154 .read()
155 .map_err(|e| ObsError::LockError(format!("{:?}", e)))?;
156 return Ok((m.x, m.y));
157 }
158
159 let pos = self.render_state.position.read().map_err(|_| {
160 ObsError::LockError("display render position lock poisoned".to_string())
161 })?;
162 Ok(*pos)
163 }
164
165 fn get_size(&self) -> Result<(u32, u32), ObsError> {
166 #[cfg(windows)]
167 if let Some(m) = self.child_window_handler.as_ref() {
168 let m = m
169 .read()
170 .map_err(|e| ObsError::LockError(format!("{:?}", e)))?;
171
172 return Ok((m.width, m.height));
173 }
174
175 let pointer = self.as_ptr();
176 let (width, height) = run_with_obs!(self.runtime, (pointer), move || {
177 let mut w: u32 = 0;
178 let mut h: u32 = 0;
179 unsafe {
180 libobs::obs_display_size(pointer.get_ptr(), &mut w, &mut h);
182 };
183
184 (w, h)
185 })?;
186
187 Ok((width, height))
188 }
189}